package com.android.accessibility;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import android.Manifest;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.android.accessibility.utils.Log;
import com.android.accessibility.utils.Utils;

public class PhoneManager {

    private Context mContext;

    private static PhoneManager sPhoneManager;

    private PhoneManager(Context context) {
        mContext = context;
    }

    public static PhoneManager get(Context context) {
        if (sPhoneManager == null) {
            sPhoneManager = new PhoneManager(context);
        }
        return sPhoneManager;
    }

    public String getAndroidUID() {
        String android_id = "" + getAndroidId();
        String tmDevice = "" + getDeviceId();
        UUID deviceUuid = new UUID(android_id.hashCode(),
                (long) tmDevice.hashCode() << 32);
        String deviceuId = deviceUuid.toString();
        return deviceuId;
    }

    public String getAndroidIDHashCode() {
        String machineCode = null;
        try {
            String auid = getAndroidUID();
            String md5 = Utils.string2MD5(auid);
            machineCode = md5.substring(md5.length() - 6);
        } catch(Exception e) {
            machineCode = String.valueOf(Math.abs(getAndroidId().hashCode()));
        }
        int verCode = 0;
        if (mContext != null) {
            verCode = Utils.getVersionCode(mContext, mContext.getPackageName());
        }
        return String.valueOf(machineCode + "v" + verCode);
    }

    public String getAndroidId() {
        String androidId = "";
        try {
            androidId = Secure.getString(mContext.getContentResolver(),
                    Secure.ANDROID_ID);
        } catch (Exception e1) {
            try {
                androidId = Settings.System.getString(
                        mContext.getContentResolver(),
                        Settings.System.ANDROID_ID);
            } catch (Exception e2) {
            }
        }
        return androidId;
    }

    /**
     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
     * or ESN for CDMA phones. Return null if device ID is not available.
     * 
     * @return
     */
    public String getDeviceId() {
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            TelephonyManager tm = (TelephonyManager) mContext
                    .getSystemService(Context.TELEPHONY_SERVICE);

            if (tm == null) {
                Log.i(Log.TAG, "get TELEPHONY_SERVICE failed.");
                return null;
            }

            return tm.getDeviceId();
        }
        return null;
    }

    public String getOsVer() {
        return Build.VERSION.RELEASE;
    }

    public String getDeviceName() {
        return Build.DEVICE;
    }

    public String getMac() {
        String macAddress = "";
        if (isGranted(Manifest.permission.ACCESS_WIFI_STATE)) {
            WifiManager wifiManager = (WifiManager) mContext
                    .getSystemService(Context.WIFI_SERVICE);
            WifiInfo info = wifiManager.getConnectionInfo();
            macAddress = info.getMacAddress();
        }
        macAddress = macAddress == null ? "" : macAddress.replaceAll(":", "-");
        return macAddress.toUpperCase();
    }

    public String getSimType() {
        int cardState = -1;
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
                String operator = tm.getSimOperator();

                if (operator != null) {
                    if (operator.equals("46000") || operator.equals("46002")
                            || operator.equals("46007")) {
                        cardState = 0; // 绉诲�?
                    } else if (operator.equals("46001")) {
                        cardState = 1; // 鑱旈�?
                    } else if (operator.equals("46003")) {
                        cardState = 2; // 鐢典�?
                    }
                }
            }
        }

        return String.valueOf(cardState);
    }

    public String getNetType() {
        ConnectivityManager ConnMgr = (ConnectivityManager) mContext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = ConnMgr.getActiveNetworkInfo();
        if (info != null) {
            return info.getTypeName();
        }
        return "";
    }

    public String getIccid() {
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            return tm.getSimSerialNumber();
        }
        return "";
    }

    public String getImei() {
        String imei = "";
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            imei = tm.getDeviceId();
        }
        return imei;
    }

    public String getImsi() {
        String imsi = "";
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
                imsi = tm.getSubscriberId();
            }
        }
        return imsi;
    }

    public String getPhoneNumber() {
        String phoneNumber = null;
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
                try {
                    phoneNumber = tm.getLine1Number();
                } catch (Exception e) {
                    Log.d(Log.TAG, "error : " + e);
                }
            }
        }
        return phoneNumber;
    }

    public String getProvinceCode() {
        String provinceCode = "-1";
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (isGranted(Manifest.permission.READ_PHONE_STATE)) {
            if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
                int code = parseIccId(tm.getSimSerialNumber());
                if (code > -1 && code < 10) {
                    provinceCode = "0" + String.valueOf(code);
                } else {
                    provinceCode = String.valueOf(code);
                }
            }
        }

        return provinceCode;
    }

    public String getAppVer() {
        String appVer = "";
        try {
            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), 0);
            appVer = String.valueOf(pi.versionCode);
        } catch (NameNotFoundException e) {
            Log.e(Log.TAG, "error : " + e);
        } catch (Exception e) {
            Log.e(Log.TAG, "error : " + e);
        }
        return appVer;
    }

    public String getChannel() {
        String assetChannel = getChannelFromAsset();
        if (TextUtils.isEmpty(assetChannel)) {
            assetChannel = getChannelFromMeta();
        }
        return assetChannel;
    }

    public String getFromUid() {
        try {
            AssetManager am = mContext.getAssets();
            InputStream is = am.open("uid.dat");
            byte buf[] = new byte[16];
            int read = is.read(buf, 0, 16);
            is.close();
            String uid = new String(buf, 0, read);
            return uid != null ? uid : "";
        } catch (IOException e) {
            Log.d(Log.TAG, "error : " + e);
        }
        return "";
    }

    private String getChannelFromAsset() {
        try {
            AssetManager am = mContext.getAssets();
            InputStream is = am.open("data.dat");
            byte buf[] = new byte[16];
            int read = is.read(buf, 0, 16);
            is.close();
            String channel = new String(buf, 0, read);
            return channel != null ? channel : "";
        } catch (IOException e) {
            Log.d(Log.TAG, "error : " + e);
        }
        return "";
    }

    private String getChannelFromMeta() {
        try {
            ApplicationInfo appInfo = mContext.getPackageManager()
                    .getApplicationInfo(mContext.getPackageName(),
                            PackageManager.GET_META_DATA);
            return appInfo.metaData.get("channel_number").toString();
        } catch (NameNotFoundException e) {
            Log.d(Log.TAG, "error : " + e);
        } catch (Exception e) {
            Log.d(Log.TAG, "error : " + e);
        }
        return "";
    }

    private int parseIccId(String strIccid) {
        int nResult = -1;

        if (null != strIccid && strIccid.length() > 0) {
            String strTemp = strIccid.substring(0, 4);
            if (strTemp.equals("8986")) {
                strTemp = strIccid.substring(4, 6);
                if (strTemp.equals("00") || strTemp.equals("02")
                        || strTemp.equals("07")) {
                    // 绉诲姩鍙风爜
                    strTemp = strIccid.substring(6, strIccid.length());
                    nResult = parseCmcc(strTemp);
                } else if (strTemp.equals("01")) {
                    // 鑱旈�鍙风爜
                    strTemp = strIccid.substring(6, strIccid.length());
                    nResult = parseCncc(strTemp);
                } else if (strTemp.equals("03")) {
                    // 鐢典俊鍙风爜
                    strTemp = strIccid.substring(6, strIccid.length());
                    nResult = parseCtcc(strTemp);
                } else {
                    // 鏈煡缂栫爜
                    nResult = 0;
                }
            } else {
                // 绉诲姩鍙风爜锛屾病鏈夊浗闄呯紪鍙枫�鍥藉缂栧彿銆佽繍钀ュ晢缂栧�?
                nResult = parseCmcc(strTemp);
            }
        }

        return nResult;
    }

    /**
     * 瑙ｆ瀽绉诲姩iccid
     */
    private int parseCmcc(String strID) {
        int nResult = -1;

        if (null != strID && strID.length() > 4) {
            String strTemp = strID.substring(2, 4);
            try {
                nResult = Integer.parseInt(strTemp);
            } catch (Exception e) {
                Log.e(Log.TAG, "parse cmcc error: " + e);
            }
        }

        return nResult;
    }

    private int parseCncc(String strID) {
        int nResult = -1;

        if (null != strID && strID.length() >= 6) {
            String strTemp = strID.substring(2, 3);
            if (strTemp.equals("8"))
                strTemp = strID.substring(3, 5);
            else
                strTemp = strID.substring(4, 6);

            try {
                nResult = Integer.parseInt(strTemp);
            } catch (Exception e) {
                Log.e(Log.TAG, "parse cncc error: " + e);
            }

            if (10 == nResult) // 鍐呰挋鍙�?
                nResult = 5;
            else if (11 == nResult) // 鍖椾�?
                nResult = 1;
            else if (13 == nResult) // 澶╂�?
                nResult = 2;
            else if (17 == nResult) // 灞变�?
                nResult = 15;
            else if (18 == nResult) // 娌冲�?
                nResult = 3;
            else if (19 == nResult) // 灞辫�?
                nResult = 4;
            else if (30 == nResult) // 瀹夊�?
                nResult = 12;
            else if (31 == nResult) // 涓婃�?
                nResult = 9;
            else if (34 == nResult) // 姹熻�?
                nResult = 10;
            else if (36 == nResult) // 娴欐�?
                nResult = 11;
            else if (38 == nResult) // 绂忓�?
                nResult = 13;
            else if (50 == nResult) // 娴峰�?
                nResult = 21;
            else if (51 == nResult) // 骞夸�?
                nResult = 19;
            else if (59 == nResult) // 骞胯�?
                nResult = 20;
            else if (70 == nResult) // 闈掓�?
                nResult = 28;
            else if (71 == nResult) // �?���?
                nResult = 17;
            else if (74 == nResult) // �?���?
                nResult = 18;
            else if (75 == nResult) // 姹熻�?
                nResult = 14;
            else if (76 == nResult) // 娌冲�?
                nResult = 16;
            else if (79 == nResult) // 瑗胯�?
                nResult = 25;
            else if (81 == nResult) // 鍥涘�?
                nResult = 22;
            else if (83 == nResult) // 閲嶅�?
                nResult = 31;
            else if (84 == nResult) // 闄曡�?
                nResult = 26;
            else if (85 == nResult) // 璐靛�?
                nResult = 23;
            else if (86 == nResult) // 浜戝�?
                nResult = 24;
            else if (87 == nResult) // 鐢樿�?
                nResult = 27;
            else if (88 == nResult) // 瀹佸�?
                nResult = 29;
            else if (89 == nResult) // 鏂扮�?
                nResult = 30;
            else if (90 == nResult) // 鍚夋�?
                nResult = 7;
            else if (91 == nResult) // 杈藉�?
                nResult = 6;
            else if (97 == nResult) // 榛戦緳姹�?
                nResult = 8;
            else
                nResult = 0;
        }

        return nResult;
    }

    /**
     * 瑙ｆ瀽鐢典俊iccid
     */
    private int parseCtcc(String strID) {
        int nResult = -1;

        if (null != strID && strID.length() >= 6) {
            String strTemp = strID.substring(4, 7);

            try {
                nResult = Integer.parseInt(strTemp);
            } catch (Exception e) {
                Log.e(Log.TAG, "parse ctcc error: " + e);
            }

            if (10 == nResult) // 鍖椾�?
                nResult = 1;
            else if (21 == nResult) // 涓婃�?
                nResult = 9;
            else if (22 == nResult) // 澶╂�?
                nResult = 2;
            else if (23 == nResult) // 閲嶅�?
                nResult = 31;
            else if (310 <= nResult && 340 >= nResult) // 娌冲�?
                nResult = 3;
            else if (349 <= nResult && 359 >= nResult) // 灞辫�?
                nResult = 4;
            else if (470 <= nResult && 483 >= nResult) // 鍐呰挋鍙�?
                nResult = 5;
            else if ((410 <= nResult && 429 >= nResult) || 24 == nResult) // 杈藉�?
                nResult = 6;
            else if (431 <= nResult && 448 >= nResult) // 鍚夋�?
                nResult = 7;
            else if (451 <= nResult && 469 >= nResult) // 榛戦緳姹�?
                nResult = 8;
            else if ((510 <= nResult && 527 >= nResult) || 25 == nResult) // 姹熻�?
                nResult = 10;
            else if (570 <= nResult && 580 >= nResult) // 娴欐�?
                nResult = 11;
            else if (550 <= nResult && 566 >= nResult) // 瀹夊�?
                nResult = 12;
            else if (591 <= nResult && 599 >= nResult) // 绂忓�?
                nResult = 13;
            else if ((790 <= nResult && 799 >= nResult) || 701 == nResult) // 姹熻�?
                nResult = 14;
            else if ((530 <= nResult && 546 >= nResult)
                    || (631 <= nResult && 635 >= nResult)) // 灞变�?
                nResult = 15;
            else if (370 <= nResult && 398 >= nResult) // 娌冲�?
                nResult = 16;
            else if ((710 <= nResult && 728 >= nResult) || 27 == nResult) // �?���?
                nResult = 17;
            else if (730 <= nResult && 746 >= nResult) // �?���?
                nResult = 18;
            else if ((660 <= nResult && 668 >= nResult)
                    || (750 <= nResult && 769 >= nResult) || 20 == nResult) // 骞夸�?
                nResult = 19;
            else if (770 <= nResult && 779 >= nResult) // 骞胯�?
                nResult = 20;
            else if (898 == nResult) // 娴峰�?
                nResult = 21;
            else if ((812 <= nResult && 839 >= nResult) || 28 == nResult) // 鍥涘�?
                nResult = 22;
            else if (851 <= nResult && 859 >= nResult) // 璐靛�?
                nResult = 23;
            else if ((691 <= nResult && 692 >= nResult)
                    || (870 <= nResult && 888 >= nResult)) // 浜戝�?
                nResult = 24;
            else if (891 <= nResult && 897 >= nResult) // 瑗胯�?
                nResult = 25;
            else if ((910 <= nResult && 919 >= nResult) || 29 == nResult) // 闄曡�?
                nResult = 26;
            else if (930 <= nResult && 943 >= nResult) // 鐢樿�?
                nResult = 27;
            else if (951 <= nResult && 955 >= nResult) // 瀹佸�?
                nResult = 29;
            else if (970 <= nResult && 979 >= nResult) // 闈掓�?
                nResult = 28;
            else if ((901 <= nResult && 909 >= nResult)
                    || (990 <= nResult && 999 >= nResult)) // 鏂扮�?
                nResult = 30;
            else
                nResult = 0;
        }
        return nResult;
    }

    private boolean isGranted(String permission) {
        return mContext.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }
}
